package com.yanyu.space.codegen.service.impl;

import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yanyu.space.codegen.bean.enums.AttrType;
import com.yanyu.space.codegen.bean.po.Attr;
import com.yanyu.space.codegen.bean.po.DsSetting;
import com.yanyu.space.codegen.bean.po.Template;
import com.yanyu.space.codegen.bean.vo.code.GeneratorCodeSearchVo;
import com.yanyu.space.codegen.bean.vo.dssetting.ColumnInfoVo;
import com.yanyu.space.codegen.bean.vo.dssetting.TableInfoVo;
import com.yanyu.space.codegen.dao.AttrMapper;
import com.yanyu.space.codegen.dao.DsSettingMapper;
import com.yanyu.space.codegen.dao.TemplateDescMapper;
import com.yanyu.space.codegen.dao.TemplateMapper;
import com.yanyu.space.codegen.service.IGeneratorCodeService;
import com.yanyu.space.codegen.util.DyncDataSourceUtil;
import com.yanyu.space.codegen.util.GeneratorCodeUtil;
import com.yanyu.space.codegen.util.strategy.ICustomAttrStrategy;
import com.yanyu.space.common.core.exception.DataNotFoundException;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipOutputStream;

/**
 *
 * @author yanyu
 * @date 2020/12/1
 */
@Service
public class GeneratorCodeServiceImpl implements IGeneratorCodeService {

    private DsSettingMapper dsSettingMapper;
    private TemplateMapper templateMapper;
    private AttrMapper attrMapper;

    public GeneratorCodeServiceImpl(DsSettingMapper dsSettingMapper,
                                    TemplateMapper templateMapper,
                                    AttrMapper attrMapper,
                                    TemplateDescMapper templateDescMapper,
                                    @Autowired(required = false) Map<String, ICustomAttrStrategy> customAttrStrategyMap) {
        this.dsSettingMapper = dsSettingMapper;
        this.templateMapper = templateMapper;
        this.attrMapper = attrMapper;
        GeneratorCodeUtil.init(customAttrStrategyMap, templateDescMapper);
    }

    @Override
    public byte[] generatorCode(GeneratorCodeSearchVo vo) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        // 1. 获取数据连接信息
        DsSetting dsSetting = dsSettingMapper.selectById(vo.getDsId());
        if(dsSetting == null) {
            throw new DataNotFoundException();
        }

        // 2. 获取分组下的模板
        List<Template> templates = templateMapper.selectList(Wrappers.<Template>lambdaQuery().eq(Template::getTemplateGroupId, vo.getTemplateGroupId()));

        // 3. 获取分组下自定义属性
        List<Attr> customAttrs = attrMapper.selectList(Wrappers.<Attr>lambdaQuery().eq(Attr::getType, AttrType.CUSTOM));

        // 4. 代码生成逻辑
        Set<String> tables = vo.getTableNames();
        tables.stream().forEach(tableName -> {
            // 4.1 获取表信息
            TableInfoVo tableInfoVo = DyncDataSourceUtil.getTableInfo(dsSetting.getUrl(), dsSetting.getName(), dsSetting.getUsername(), dsSetting.getPassword(), tableName);
            // 4.2 获取表列信息
            List<ColumnInfoVo> columnInfoVos = DyncDataSourceUtil.listColumn(dsSetting.getUrl(), dsSetting.getName(), dsSetting.getUsername(), dsSetting.getPassword(), tableName);
            // 4.3 代码生成
            GeneratorCodeUtil.generator(templates, vo, tableInfoVo, columnInfoVos, customAttrs, zip);
        });

        // 5. 关闭流
        IoUtil.close(zip);
        return outputStream.toByteArray();
    }
}
